package Resources.Utils;

import MVC.Models.Peca;
import MVC.Models.Posicao;
import Resources.Enums.Cor;
import Resources.Enums.Quadrante;

import java.security.Security;

public class Matrix<E> {
    private int M;             // number of rows
    private int N;             // number of columns
    private Posicao[][] data;   // M-by-N array

    // create M-by-N matrix of 0's
    public Matrix(int M, int N) {
        this.M = M;
        this.N = N;
        this.data = new Posicao[M][N];
        for (int i = 0; i < M; i++)
            for (int j = 0; j < N; j++)
                this.data[i][j] = new Posicao();
    }

    public void show() {
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++){
                    System.out.print(data[i][j].getPeca().getCor());
            }
            System.out.println();
        }
    }

    public void turnTable(Quadrante quad, boolean lado){
        Posicao[][] quadranteReal = this.getQuadrante(quad);

        if(lado==true)
            this.turnRight(quadranteReal);
        else
            this.turnLeft(quadranteReal);
    }

    private Posicao[][] getQuadrante(Quadrante quad) {
        Posicao[][] retorno = new Posicao[3][3];
        switch(quad){
            case PRIMEIRO:
                for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++)
                        retorno[i][j] = this.data[i][j];
                break;
            case SEGUNDO:
                for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++)
                        retorno[i][j] = this.data[i][j+3];
                break;
            case TERCEIRO:
                 for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++)
                        retorno[i][j] = this.data[i+3][j];
                break;
            case QUARTO:
                for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++)
                        retorno[i][j] = this.data[i+3][j+3];
                break;
        }
        return retorno;
    }

    public void populate(){
        for (int i = 0; i < M; i++) {
            data[i][0].setPeca(new Peca(Cor.PRETO));
            data[i][1].setPeca(new Peca(Cor.BRANCO));
            data[i][2].setPeca(new Peca(Cor.VAZIO));
            data[i][3].setPeca(new Peca(Cor.PRETO));
            data[i][4].setPeca(new Peca(Cor.BRANCO));
            data[i][5].setPeca(new Peca(Cor.VAZIO));
            }
        }


    public Posicao[][] cloneQuadrante(Posicao[][] quadranteReal){
        Posicao[][] pos = new Posicao[quadranteReal.length][quadranteReal.length];
        for (int i = 0; i < quadranteReal.length; i++)
            for (int j = 0; j < quadranteReal.length; j++){
                Peca novaPeca = new Peca();
                novaPeca.setCor(this.data[i][j].getPeca().getCor());
                pos[i][j] = new Posicao();
                pos[i][j].setPeca(novaPeca);
            }

     return pos;
    }

    public void turnRight(Posicao[][] quadranteReal){

        Posicao[][] oClone = this.cloneQuadrante(quadranteReal);

        quadranteReal[0][0].getPeca().setCor(oClone[2][0].getPeca().getCor());

        quadranteReal[0][1].getPeca().setCor(oClone[1][0].getPeca().getCor());

        quadranteReal[0][2].getPeca().setCor(oClone[0][0].getPeca().getCor());

        quadranteReal[1][0].getPeca().setCor(oClone[2][1].getPeca().getCor());

        quadranteReal[1][2].getPeca().setCor(oClone[0][1].getPeca().getCor());

        quadranteReal[2][0].getPeca().setCor(oClone[2][2].getPeca().getCor());

        quadranteReal[2][1].getPeca().setCor(oClone[1][2].getPeca().getCor());

        quadranteReal[2][2].getPeca().setCor(oClone[0][2].getPeca().getCor());
    }

        public void turnLeft(Posicao[][] quadranteReal){
        Posicao[][] oClone = this.cloneQuadrante(quadranteReal);

        quadranteReal[0][0].getPeca().setCor(oClone[0][2].getPeca().getCor());

        quadranteReal[0][1].getPeca().setCor(oClone[1][2].getPeca().getCor());

        quadranteReal[0][2].getPeca().setCor(oClone[2][2].getPeca().getCor());

        quadranteReal[1][0].getPeca().setCor(oClone[0][1].getPeca().getCor());

        quadranteReal[1][2].getPeca().setCor(oClone[2][1].getPeca().getCor());

        quadranteReal[2][0].getPeca().setCor(oClone[0][0].getPeca().getCor());

        quadranteReal[2][1].getPeca().setCor(oClone[1][0].getPeca().getCor());

        quadranteReal[2][2].getPeca().setCor(oClone[2][0].getPeca().getCor());
    }

    public Posicao[][] getPosicoes(){
        return this.data;
    }
   // create and return the N-by-N identity matrix

    /** public static Matrix identity(int N) {
        Matrix I = new Matrix(N, N);
        for (int i = 0; i < N; i++)
            I.data[i][i] = 1;
        return I;
    }

    // swap rows i and j
    private void swap(int i, int j) {
        Object[] temp = data[i];
        data[i] = data[j];
        data[j] = temp;
    }

    // create and return the transpose of the invoking matrix
    public Matrix transpose() {
        Matrix A = new Matrix(N, M);
        for (int i = 0; i < M; i++)
            for (int j = 0; j < N; j++)
                A.data[j][i] = this.data[i][j];
        return A;
    }

    // does A = B exactly?
    public boolean eq(Matrix B) {
        Matrix A = this;
        if (B.M != A.M || B.N != A.N) throw new RuntimeException("Illegal matrix dimensions.");
        for (int i = 0; i < M; i++)
            for (int j = 0; j < N; j++)
                if (A.data[i][j] != B.data[i][j])
                    return false;
        return true;
    }
        **/
    // print matrix to standard output


}
